{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "; ModuleID = \"name\"\n",
      "target triple = \"unknown-unknown-unknown\"\n",
      "target datalayout = \"\"\n",
      "\n",
      "define i32 @\"fpadd\"(i32 %\".1\", i32 %\".2\") \n",
      "{\n",
      "entry:\n",
      "  %\".4\" = add i32 %\".1\", %\".2\"\n",
      "  ret i32 %\".4\"\n",
      "}\n",
      "\n"
     ]
    }
   ],
   "source": [
    "from llvmlite import ir\n",
    "\n",
    "# Create some useful types\n",
    "intty = ir.IntType(32)\n",
    "fnty = ir.FunctionType(intty, (intty, intty))\n",
    "\n",
    "# Create an empty module...\n",
    "module = ir.Module(name=\"name\")\n",
    "# and declare a function named \"fpadd\" inside it\n",
    "func = ir.Function(module, fnty, name=\"fpadd\")\n",
    "\n",
    "# Now implement the function\n",
    "block = func.append_basic_block(name=\"entry\")\n",
    "\n",
    "\n",
    "added = ir.Instruction(block, intty, 'add', [\n",
    "    func.args[0],\n",
    "    func.args[1]\n",
    "])\n",
    "block.instructions = [\n",
    "    added,\n",
    "    ir.Ret(block, 'ret', added)\n",
    "]\n",
    "\n",
    "# Print the module IR\n",
    "print(module)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from llvmlite import binding as llvm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def execute(ir_mod):\n",
    "    llvm.initialize()\n",
    "    llvm.initialize_native_target()\n",
    "    llvm.initialize_native_asmprinter()\n",
    "\n",
    "    llmod = llvm.parse_assembly(str(ir_mod))\n",
    "\n",
    "    print('optimized'.center(80, '-'))\n",
    "    pmb = llvm.create_pass_manager_builder()\n",
    "    pmb.opt_level = 1\n",
    "    pm = llvm.create_module_pass_manager()\n",
    "    pmb.populate(pm)\n",
    "    pm.run(llmod)\n",
    "    print(llmod)\n",
    "\n",
    "    target_machine = llvm.Target.from_default_triple().create_target_machine()\n",
    "\n",
    "    with llvm.create_mcjit_compiler(llmod, target_machine) as ee:\n",
    "        ee.finalize_object()\n",
    "        cfptr = ee.get_function_address(\"fpadd\")\n",
    "\n",
    "        from ctypes import CFUNCTYPE, c_int\n",
    "\n",
    "        cfunc = CFUNCTYPE(c_int, c_int, c_int)(cfptr)\n",
    "\n",
    "        # TEST\n",
    "        for i in range(12):\n",
    "            res = cfunc(i, i)\n",
    "            print('fib({}) = {}'.format(i, res))\n",
    "\n",
    "        # Get CFG\n",
    "        ll_fib_more = llmod.get_function('fpadd')\n",
    "        cfg = llvm.get_function_cfg(ll_fib_more)\n",
    "        llvm.view_dot_graph(cfg, view=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-----------------------------------optimized------------------------------------\n",
      "; ModuleID = '<string>'\n",
      "source_filename = \"<string>\"\n",
      "target triple = \"unknown-unknown-unknown\"\n",
      "\n",
      "; Function Attrs: norecurse nounwind readnone\n",
      "define i32 @fpadd(i32 %.1, i32 %.2) local_unnamed_addr #0 {\n",
      "entry:\n",
      "  %.4 = add i32 %.2, %.1\n",
      "  ret i32 %.4\n",
      "}\n",
      "\n",
      "attributes #0 = { norecurse nounwind readnone }\n",
      "\n",
      "fib(0) = 0\n",
      "fib(1) = 2\n",
      "fib(2) = 4\n",
      "fib(3) = 6\n",
      "fib(4) = 8\n",
      "fib(5) = 10\n",
      "fib(6) = 12\n",
      "fib(7) = 14\n",
      "fib(8) = 16\n",
      "fib(9) = 18\n",
      "fib(10) = 20\n",
      "fib(11) = 22\n"
     ]
    }
   ],
   "source": [
    "execute(module)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting git+https://github.com/sklam/etude-tict.git\n",
      "  Cloning https://github.com/sklam/etude-tict.git to /private/var/folders/m7/t8dvwtnn32z84333p845tly40000gn/T/pip-req-build-7mx62p4k\n",
      "fatal: unable to access 'https://github.com/sklam/etude-tict.git/': Could not resolve host: github.com\n",
      "\u001b[31mCommand \"git clone -q https://github.com/sklam/etude-tict.git /private/var/folders/m7/t8dvwtnn32z84333p845tly40000gn/T/pip-req-build-7mx62p4k\" failed with error code 128 in None\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "!pip install git+https://github.com/sklam/etude-tict.git"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "jupyter": {
     "source_hidden": true
    }
   },
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Define a mini-language to compute the fibonnaci sequence.\n",
    "\n",
    "Uses LLVM for codegeneration.\n",
    "\"\"\"\n",
    "\n",
    "import inspect\n",
    "from llvmlite import ir\n",
    "from llvmlite import binding as llvm\n",
    "\n",
    "from kvbacker import (\n",
    "    ResourceManager,\n",
    "    Managed,\n",
    "    ManagedList,\n",
    "    graphviz_render_revisions,\n",
    ")\n",
    "\n",
    "\n",
    "class FunctionCollections(Managed):\n",
    "    pass\n",
    "\n",
    "\n",
    "class ContextResources(ResourceManager):\n",
    "    pass\n",
    "\n",
    "\n",
    "class Expr(Managed):\n",
    "    pass\n",
    "\n",
    "\n",
    "class FunctionDecl(Expr):\n",
    "    def init(self, name):\n",
    "        self.name = name\n",
    "\n",
    "    def __call__(self, *args):\n",
    "        args = self._resmngr.new(\n",
    "            ArgListVal,\n",
    "            [_fix_value(self._resmngr, x) for x in args],\n",
    "        )\n",
    "        return self._resmngr.new(CallVal, op=self, args=args)\n",
    "\n",
    "    def codegen(self, cgstate):\n",
    "        mod = cgstate.builder.module\n",
    "        return mod.get_global(self.name)\n",
    "\n",
    "\n",
    "class FunctionDefn(Expr):\n",
    "    def init(self, name, expr, arity):\n",
    "        self.name = name\n",
    "        self.expr = expr\n",
    "        self.arity = arity\n",
    "\n",
    "    def codegen_definition(self, ir_mod):\n",
    "        fn = self.codegen_declare(ir_mod)\n",
    "        fn.calling_convention = 'fastcc'\n",
    "        entry_block = fn.append_basic_block('entry')\n",
    "        main_block = fn.append_basic_block('main')\n",
    "        irbuilder = ir.IRBuilder()\n",
    "        cgstate = CodegenState(irbuilder, entry_block)\n",
    "        irbuilder.position_at_end(main_block)\n",
    "        value = self.expr.codegen(cgstate)\n",
    "        irbuilder.ret(value)\n",
    "        # Clean up\n",
    "        irbuilder.position_at_end(entry_block)\n",
    "        irbuilder.branch(main_block)\n",
    "\n",
    "    def codegen_declare(self, ir_mod):\n",
    "        try:\n",
    "            return ir_mod.get_global(self.name)\n",
    "        except KeyError:\n",
    "            argty = ir.IntType(32)\n",
    "            fnty = ir.FunctionType(argty, [argty] * self.arity)\n",
    "            fn = ir.Function(ir_mod, fnty, name=self.name)\n",
    "            return fn\n",
    "\n",
    "\n",
    "class ConstVal(Expr):\n",
    "    def init(self, value):\n",
    "        self.value = value\n",
    "\n",
    "    def codegen(self, cgstate):\n",
    "        intty = ir.IntType(32)\n",
    "        return intty(self.value)\n",
    "\n",
    "\n",
    "class ParamVal(Expr):\n",
    "    def init(self, name, pos):\n",
    "        self.name = name\n",
    "        self.pos = pos\n",
    "\n",
    "    def codegen(self, cgstate):\n",
    "        builder = cgstate.builder\n",
    "        fn = builder.function\n",
    "        arg = fn.args[self.pos]\n",
    "        return arg\n",
    "\n",
    "\n",
    "class CallVal(Expr):\n",
    "    def init(self, op, args):\n",
    "        self.op = op\n",
    "        self.args = args\n",
    "\n",
    "    def codegen(self, cgstate):\n",
    "        if isinstance(self.op, Expr):\n",
    "            assert isinstance(self.op, FunctionDecl)\n",
    "            callee = self.op.codegen(cgstate)\n",
    "            args = [a.codegen(cgstate) for a in self.args]\n",
    "            return cgstate.builder.call(callee, args)\n",
    "        else:\n",
    "            builder = cgstate.builder\n",
    "            assert len(self.args) == 2\n",
    "            lhs = self.args[0].codegen(cgstate)\n",
    "            rhs = self.args[1].codegen(cgstate)\n",
    "            if self.op == '+':\n",
    "                res = builder.add(lhs, rhs)\n",
    "            elif self.op == '-':\n",
    "                res = builder.sub(lhs, rhs)\n",
    "            elif self.op == '>':\n",
    "                res = builder.icmp_signed('>', lhs, rhs)\n",
    "            elif self.op == '==':\n",
    "                res = builder.icmp_signed('==', lhs, rhs)\n",
    "            else:\n",
    "                raise NotImplementedError(self.op)\n",
    "            return res\n",
    "\n",
    "\n",
    "class ArgListVal(ManagedList):\n",
    "    pass\n",
    "\n",
    "\n",
    "class IfElseVal(Expr):\n",
    "    def init(self, pred, then_expr, else_expr):\n",
    "        self.pred = pred\n",
    "        self.then_expr = then_expr\n",
    "        self.else_expr = else_expr\n",
    "\n",
    "    def codegen(self, cgstate):\n",
    "        builder = cgstate.builder\n",
    "        bb_then = builder.append_basic_block('then')\n",
    "        bb_else = builder.append_basic_block('else')\n",
    "        bb_after = builder.append_basic_block('endif')\n",
    "\n",
    "        pred = self.pred.codegen(cgstate)\n",
    "        builder.cbranch(pred, bb_then, bb_else)\n",
    "\n",
    "        builder.position_at_end(cgstate.entry_block)\n",
    "        phi = builder.alloca(ir.IntType(32))\n",
    "\n",
    "        builder.position_at_end(bb_then)\n",
    "        then_value = self.then_expr.codegen(cgstate)\n",
    "        builder.store(then_value, phi)\n",
    "        builder.branch(bb_after)\n",
    "\n",
    "        builder.position_at_end(bb_else)\n",
    "        else_value = self.else_expr.codegen(cgstate)\n",
    "        builder.store(else_value, phi)\n",
    "        builder.branch(bb_after)\n",
    "\n",
    "        builder.position_at_end(bb_after)\n",
    "        return builder.load(phi)\n",
    "\n",
    "\n",
    "class Context:\n",
    "    def __init__(self):\n",
    "        self._rm = ContextResources()\n",
    "        self._declfuncs = {}\n",
    "        self._definitions = {}\n",
    "\n",
    "    def define(self, fn):\n",
    "        fname = fn.__name__\n",
    "        fndecl = self._rm.new(FunctionDecl, name=fname)\n",
    "        self._declfuncs[fname] = {'decl': fndecl, 'defn': fn}\n",
    "        return fndecl\n",
    "\n",
    "    def visualize(self):\n",
    "        return self._rm.visualize()\n",
    "\n",
    "    def codegen(self):\n",
    "        ir_mod = ir.Module()\n",
    "        for k, defn in self._definitions.items():\n",
    "            defn.codegen_declare(ir_mod)\n",
    "        for k, defn in self._definitions.items():\n",
    "            defn.codegen_definition(ir_mod)\n",
    "        return ir_mod\n",
    "\n",
    "    def materialize(self):\n",
    "        while self._declfuncs:\n",
    "            name, info = self._declfuncs.popitem()\n",
    "            defn = info['defn']\n",
    "            defn = self._build_definition(name, defn)\n",
    "            self._definitions[name] = defn\n",
    "\n",
    "    def _build_definition(self, name, fn):\n",
    "        sig = inspect.signature(fn)\n",
    "        params = list(sig.parameters.items())\n",
    "        kwargs = {params[0][0]: self}\n",
    "        for i, (k, v) in enumerate(params[1:]):\n",
    "            kwargs[k] = self._rm.new(ParamVal, name=k, pos=i)\n",
    "        expr = fn(**kwargs)\n",
    "        defn = self._rm.new(\n",
    "            FunctionDefn, name=name, expr=expr, arity=len(params) - 1,\n",
    "        )\n",
    "        return defn\n",
    "\n",
    "    def call(self, op, args):\n",
    "        return self._rm.new(CallVal, op=op, args=self._arglist(*args))\n",
    "\n",
    "    def ifelse(self, pred, then_expr, else_expr):\n",
    "        return self._rm.new(\n",
    "            IfElseVal,\n",
    "            pred=pred,\n",
    "            then_expr=self._fix_value(then_expr),\n",
    "            else_expr=self._fix_value(else_expr),\n",
    "        )\n",
    "\n",
    "    def _arglist(self, *args):\n",
    "        return self._rm.new(\n",
    "            ArgListVal,\n",
    "            values=[self._fix_value(x) for x in args],\n",
    "        )\n",
    "\n",
    "    def _fix_value(self, val):\n",
    "        return _fix_value(self._rm, val)\n",
    "\n",
    "\n",
    "def _fix_value(rm, val):\n",
    "    if isinstance(val, Expr):\n",
    "        return val\n",
    "    else:\n",
    "        return rm.new(ConstVal, value=val)\n",
    "\n",
    "\n",
    "class CodegenState:\n",
    "    def __init__(self, ir_builder, entry_block):\n",
    "        self.builder = ir_builder\n",
    "        self.entry_block = entry_block\n",
    "\n",
    "\n",
    "def make_c_wrapper(fn_callee):\n",
    "    mod = fn_callee.module\n",
    "    fnty = fn_callee.function_type\n",
    "    fn = ir.Function(mod, fnty, name='entry_' + fn_callee.name)\n",
    "    builder = ir.IRBuilder(fn.append_basic_block())\n",
    "    builder.ret(builder.call(fn_callee, fn.args))\n",
    "\n",
    "\n",
    "def execute(ir_mod):\n",
    "    llvm.initialize()\n",
    "    llvm.initialize_native_target()\n",
    "    llvm.initialize_native_asmprinter()\n",
    "\n",
    "    llmod = llvm.parse_assembly(str(ir_mod))\n",
    "\n",
    "    print('optimized'.center(80, '-'))\n",
    "    pmb = llvm.create_pass_manager_builder()\n",
    "    pmb.opt_level = 0\n",
    "    pm = llvm.create_module_pass_manager()\n",
    "    pmb.populate(pm)\n",
    "    pm.run(llmod)\n",
    "    print(llmod)\n",
    "\n",
    "    target_machine = llvm.Target.from_default_triple().create_target_machine()\n",
    "\n",
    "    with llvm.create_mcjit_compiler(llmod, target_machine) as ee:\n",
    "        ee.finalize_object()\n",
    "        cfptr = ee.get_function_address(\"entry_fib\")\n",
    "\n",
    "        from ctypes import CFUNCTYPE, c_int\n",
    "\n",
    "        cfunc = CFUNCTYPE(c_int, c_int)(cfptr)\n",
    "\n",
    "        # TEST\n",
    "        for i in range(12):\n",
    "            res = cfunc(i)\n",
    "            print('fib({}) = {}'.format(i, res))\n",
    "\n",
    "        # Get CFG\n",
    "        ll_fib_more = llmod.get_function('fib_more')\n",
    "        cfg = llvm.get_function_cfg(ll_fib_more)\n",
    "        llvm.view_dot_graph(cfg, view=True)\n",
    "\n",
    "\n",
    "def test():\n",
    "    context = Context()\n",
    "\n",
    "    @context.define\n",
    "    def fib(ctx, n):\n",
    "        return fib_more(n, 0, 1)\n",
    "\n",
    "    @context.define\n",
    "    def fib_more(ctx, n, a, b):\n",
    "        pred_cont = ctx.call('>', [n, 1])\n",
    "        minus1 = ctx.call('-', [n, 1])\n",
    "        ab = ctx.call('+', [a, b])\n",
    "        added = fib_more(minus1, b, ab)\n",
    "\n",
    "        n_eq_1 = ctx.call('==', [n, 1])\n",
    "        return ctx.ifelse(pred_cont, added,\n",
    "                          ctx.ifelse(n_eq_1, b, a))\n",
    "\n",
    "    context.materialize()\n",
    "\n",
    "    ir_mod = context.codegen()\n",
    "    context.visualize().render(view=True)\n",
    "    make_c_wrapper(ir_mod.get_global('fib'))\n",
    "    print(ir_mod)\n",
    "\n",
    "    execute(ir_mod)\n",
    "\n",
    "    rendered = graphviz_render_revisions(context._rm)\n",
    "    return ir_mod\n",
    "    with open('example_minilang.html', 'w') as fout:\n",
    "        print(rendered, file=fout)\n",
    "\n",
    "\n",
    "# if __name__ == '__main__':\n",
    "#     test()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'test' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-13-95abf615634d>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmod\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m: name 'test' is not defined"
     ]
    }
   ],
   "source": [
    "mod = test()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('_ZN8__main__11loop_fn$241E5ArrayIxLi1E1C7mutable7alignedE',\n",
       "              <ir.Function '_ZN8__main__11loop_fn$241E5ArrayIxLi1E1C7mutable7alignedE' of type 'i32 (i64*, {i8*, i32}**, i8*, i8*, i64, i64, i64*, i64, i64)*'>),\n",
       "             ('_ZN7cpython8__main__11loop_fn$241E5ArrayIxLi1E1C7mutable7alignedE',\n",
       "              <ir.Function '_ZN7cpython8__main__11loop_fn$241E5ArrayIxLi1E1C7mutable7alignedE' of type 'i8* (i8*, i8*, i8*)*'>),\n",
       "             ('PyArg_UnpackTuple',\n",
       "              <ir.Function 'PyArg_UnpackTuple' of type 'i32 (i8*, i8*, i64, i64, ...)*'>),\n",
       "             ('.const.loop_fn',\n",
       "              <ir.GlobalVariable '.const.loop_fn' of type '[8 x i8]*'>),\n",
       "             ('_ZN08NumbaEnv8__main__11loop_fn$241E5ArrayIxLi1E1C7mutable7alignedE',\n",
       "              <ir.GlobalVariable '_ZN08NumbaEnv8__main__11loop_fn$241E5ArrayIxLi1E1C7mutable7alignedE' of type 'i8**'>),\n",
       "             ('PyErr_SetString',\n",
       "              <ir.Function 'PyErr_SetString' of type 'void (i8*, i8*)*'>),\n",
       "             ('PyExc_RuntimeError',\n",
       "              <ir.GlobalVariable 'PyExc_RuntimeError' of type 'i8*'>),\n",
       "             ('.const.missing Environment',\n",
       "              <ir.GlobalVariable '.const.missing Environment' of type '[20 x i8]*'>),\n",
       "             ('NRT_adapt_ndarray_from_python',\n",
       "              <ir.Function 'NRT_adapt_ndarray_from_python' of type 'i32 (i8*, i8*)*'>),\n",
       "             ('PyExc_TypeError',\n",
       "              <ir.GlobalVariable 'PyExc_TypeError' of type 'i8*'>),\n",
       "             (\".const.can't unbox array from PyObject into native value.  The object maybe of a different type\",\n",
       "              <ir.GlobalVariable \".const.can't unbox array from PyObject into native value.  The object maybe of a different type\" of type '[89 x i8]*'>),\n",
       "             ('NRT_decref', <ir.Function 'NRT_decref' of type 'void (i8*)*'>),\n",
       "             ('_Py_NoneStruct',\n",
       "              <ir.GlobalVariable '_Py_NoneStruct' of type 'i8*'>),\n",
       "             ('Py_IncRef', <ir.Function 'Py_IncRef' of type 'void (i8*)*'>),\n",
       "             ('PyLong_FromLongLong',\n",
       "              <ir.Function 'PyLong_FromLongLong' of type 'i8* (i64)*'>),\n",
       "             ('PyErr_Clear', <ir.Function 'PyErr_Clear' of type 'void ()*'>),\n",
       "             ('numba_unpickle',\n",
       "              <ir.Function 'numba_unpickle' of type 'i8* (i8*, i32)*'>),\n",
       "             ('numba_do_raise',\n",
       "              <ir.Function 'numba_do_raise' of type 'void (i8*)*'>),\n",
       "             ('PyErr_SetNone',\n",
       "              <ir.Function 'PyErr_SetNone' of type 'void (i8*)*'>),\n",
       "             ('PyExc_StopIteration',\n",
       "              <ir.GlobalVariable 'PyExc_StopIteration' of type 'i8*'>),\n",
       "             ('PyExc_SystemError',\n",
       "              <ir.GlobalVariable 'PyExc_SystemError' of type 'i8*'>),\n",
       "             ('.const.unknown error when calling native function',\n",
       "              <ir.GlobalVariable '.const.unknown error when calling native function' of type '[43 x i8]*'>)])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mod.globals"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "fib_more = mod.globals['fib_more']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0;31mType:\u001b[0m        Function\n",
       "\u001b[0;31mString form:\u001b[0m\n",
       "define fastcc i32 @\"fib_more\"(i32 %\".1\", i32 %\".2\", i32 %\".3\") \n",
       "{\n",
       "entry:\n",
       "  %\".7\" = alloca i32\n",
       "  %\".15\" = alloca i32\n",
       "  br label %\"main\"\n",
       "main:\n",
       "  %\".5\" = icmp sgt i32 %\".1\", 1\n",
       "  br i1 %\".5\", label %\"then\", label %\"else\"\n",
       "then:\n",
       "  %\".8\" = sub i32 %\".1\", 1\n",
       "  %\".9\" = add i32 %\".2\", %\".3\"\n",
       "  %\".10\" = call fastcc i32 @\"fib_more\"(i32 %\".8\", i32 %\".3\", i32 %\".9\")\n",
       "  store i32 %\".10\", i32* %\".7\"\n",
       "  br label %\"endif\"\n",
       "else:\n",
       "  %\".13\" = icmp eq i32 %\".1\", 1\n",
       "  br i1 %\".13\", label %\"then.1\", label %\"else.1\"\n",
       "endif:\n",
       "  %\".23\" = load i32, i32* %\".7\"\n",
       "  ret i32 %\".23\"\n",
       "then.1:\n",
       "  store i32 %\".3\", i32* %\".15\"\n",
       "  br label %\"endif.1\"\n",
       "else.1:\n",
       "  store i32 %\".2\", i32* %\".15\"\n",
       "  br label %\"endif.1\"\n",
       "endif.1:\n",
       "  %\".20\" = load i32, i32* %\".15\"\n",
       "  store i32 %\".20\", i32* %\".7\"\n",
       "  br label %\"endif\"\n",
       "}\n",
       "\u001b[0;31mFile:\u001b[0m        /usr/local/miniconda3/envs/metadsl/lib/python3.7/site-packages/llvmlite/ir/values.py\n",
       "\u001b[0;31mSource:\u001b[0m     \n",
       "\u001b[0;32mclass\u001b[0m \u001b[0mFunction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mGlobalValue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0m_HasMetadata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m\"\"\"Represent a LLVM Function but does uses a Module as parent.\u001b[0m\n",
       "\u001b[0;34m    Global Values are stored as a set of dependencies (attribute `depends`).\u001b[0m\n",
       "\u001b[0;34m    \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmodule\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mftype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32massert\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mftype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtypes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mType\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mFunction\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodule\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mftype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mas_pointer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mftype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mftype\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mscope\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_utils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mNameScope\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblocks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattributes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mFunctionAttributes\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mArgument\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                           \u001b[0;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mftype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturn_value\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mReturnValue\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mftype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturn_type\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_global\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcalling_convention\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmetadata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mmodule\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mentry_basic_block\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblocks\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mbasic_blocks\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblocks\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mappend_basic_block\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mblk\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mBlock\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblocks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mblk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mblk\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0minsert_basic_block\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbefore\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;34m\"\"\"Insert block before\u001b[0m\n",
       "\u001b[0;34m        \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mblk\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mBlock\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblocks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minsert\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbefore\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mblk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mblk\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mdescr_prototype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;34m\"\"\"\u001b[0m\n",
       "\u001b[0;34m        Describe the prototype (\"head\") of the function.\u001b[0m\n",
       "\u001b[0;34m        \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mstate\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"define\"\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblocks\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m\"declare\"\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mret\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturn_value\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\", \"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mname\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mattrs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattributes\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mvararg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m', ...'\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mftype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvar_arg\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mvararg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'...'\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mftype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvar_arg\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mlinkage\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinkage\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mcconv\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcalling_convention\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mprefix\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\" \"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mstate\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlinkage\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcconv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mret\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mmetadata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stringify_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mprototype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"{prefix} {name}({args}{vararg}) {attrs}{metadata}\\n\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mprefix\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mprefix\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvararg\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvararg\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mattrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mattrs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmetadata\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmetadata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mprototype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mdescr_body\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;34m\"\"\"\u001b[0m\n",
       "\u001b[0;34m        Describe of the body of the function.\u001b[0m\n",
       "\u001b[0;34m        \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mfor\u001b[0m \u001b[0mblk\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblocks\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mblk\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdescr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mdescr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdescr_prototype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblocks\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"{\\n\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdescr_body\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"}\\n\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0m__str__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mbuf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdescr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0;34m\"\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mis_declaration\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mblocks\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fib_more??"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<ir.Block 'entry' of type 'label'>,\n",
       " <ir.Block 'main' of type 'label'>,\n",
       " <ir.Block 'then' of type 'label'>,\n",
       " <ir.Block 'else' of type 'label'>,\n",
       " <ir.Block 'endif' of type 'label'>,\n",
       " <ir.Block 'then.1' of type 'label'>,\n",
       " <ir.Block 'else.1' of type 'label'>,\n",
       " <ir.Block 'endif.1' of type 'label'>]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fib_more.blocks"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "then = fib_more.blocks[2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0;31mType:\u001b[0m        Block\n",
       "\u001b[0;31mString form:\u001b[0m\n",
       "%\"then\" = then:\n",
       "  %\".8\" = sub i32 %\".1\", 1\n",
       "  %\".9\" = add i32 %\".2\", %\".3\"\n",
       "  %\".10\" = call fastcc i32 @\"fib_more\"(i32 %\".8\", i32 %\".3\", i32 %\".9\")\n",
       "  store i32 %\".10\", i32* %\".7\"\n",
       "  br label %\"endif\"\n",
       "\u001b[0;31mFile:\u001b[0m        /usr/local/miniconda3/envs/metadsl/lib/python3.7/site-packages/llvmlite/ir/values.py\n",
       "\u001b[0;31mSource:\u001b[0m     \n",
       "\u001b[0;32mclass\u001b[0m \u001b[0mBlock\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mNamedValue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m\"\"\"\u001b[0m\n",
       "\u001b[0;34m    A LLVM IR basic block. A basic block is a sequence of\u001b[0m\n",
       "\u001b[0;34m    instructions whose execution always goes from start to end.  That\u001b[0m\n",
       "\u001b[0;34m    is, a control flow instruction (branch) can only appear as the\u001b[0m\n",
       "\u001b[0;34m    last instruction, and incoming branches can only jump to the first\u001b[0m\n",
       "\u001b[0;34m    instruction.\u001b[0m\n",
       "\u001b[0;34m    \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mBlock\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtypes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mLabelType\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mscope\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mparent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mscope\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minstructions\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mterminator\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mis_terminated\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mterminator\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mfunction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mmodule\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodule\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mdescr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"{0}:\\n\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mbuf\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m\"  {0}\\n\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0minstr\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0minstr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minstructions\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mreplace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mold\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;34m\"\"\"Replace an instruction\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0mold\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"new instruction has a different type\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mpos\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minstructions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mold\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minstructions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mremove\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mold\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minstructions\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minsert\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpos\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mfor\u001b[0m \u001b[0mbb\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbasic_blocks\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0;32mfor\u001b[0m \u001b[0minstr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mbb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minstructions\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                \u001b[0minstr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreplace_usage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mold\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "then??"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<ir.Instruction '.8' of type 'i32', opname 'sub', operands (<ir.Argument '.1' of type i32>, <ir.Constant type='i32' value=1>)>,\n",
       " <ir.Instruction '.9' of type 'i32', opname 'add', operands (<ir.Argument '.2' of type i32>, <ir.Argument '.3' of type i32>)>,\n",
       " <ir.CallInstr '.10' of type 'i32', opname 'call', operands [<ir.Function 'fib_more' of type 'i32 (i32, i32, i32)*'>, <ir.Instruction '.8' of type 'i32', opname 'sub', operands (<ir.Argument '.1' of type i32>, <ir.Constant type='i32' value=1>)>, <ir.Argument '.3' of type i32>, <ir.Instruction '.9' of type 'i32', opname 'add', operands (<ir.Argument '.2' of type i32>, <ir.Argument '.3' of type i32>)>]>,\n",
       " <ir.StoreInstr '.11' of type 'void', opname 'store', operands [<ir.CallInstr '.10' of type 'i32', opname 'call', operands [<ir.Function 'fib_more' of type 'i32 (i32, i32, i32)*'>, <ir.Instruction '.8' of type 'i32', opname 'sub', operands (<ir.Argument '.1' of type i32>, <ir.Constant type='i32' value=1>)>, <ir.Argument '.3' of type i32>, <ir.Instruction '.9' of type 'i32', opname 'add', operands (<ir.Argument '.2' of type i32>, <ir.Argument '.3' of type i32>)>]>, <ir.AllocaInstr '.7' of type 'i32*', opname 'alloca', operands ()>]>,\n",
       " <ir.Branch '.12' of type 'void', opname 'br', operands [<ir.Block 'endif' of type 'label'>]>]"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "then.instructions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0;31mType:\u001b[0m            CallInstr\n",
       "\u001b[0;31mString form:\u001b[0m     %\".10\" = call fastcc i32 @\"fib_more\"(i32 %\".8\", i32 %\".3\", i32 %\".9\")\n",
       "\u001b[0;31mFile:\u001b[0m            /usr/local/miniconda3/envs/metadsl/lib/python3.7/site-packages/llvmlite/ir/instructions.py\n",
       "\u001b[0;31mSource:\u001b[0m         \n",
       "\u001b[0;32mclass\u001b[0m \u001b[0mCallInstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mInstruction\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcconv\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtail\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                 \u001b[0mfastmath\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcconv\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcalling_convention\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                      \u001b[0;32mif\u001b[0m \u001b[0mcconv\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mFunction\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                      \u001b[0;32melse\u001b[0m \u001b[0mcconv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtail\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtail\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfastmath\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mFastMathFlags\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfastmath\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattributes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mCallInstrAttributes\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;31m# Fix and validate arguments\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunction_type\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0marg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mexpected_type\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunction_type\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0;32mif\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mexpected_type\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtypes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMetaDataType\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                \u001b[0marg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mexpected_type\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                \u001b[0marg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mMetaDataArgument\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0;32mif\u001b[0m \u001b[0marg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mexpected_type\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                \u001b[0mmsg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m\"Type of #{0} arg mismatch: {1} != {2}\"\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                       \u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mi\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mexpected_type\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0marg\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0marg\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mCallInstr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunction_type\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturn_type\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                                        \u001b[0;34m\"call\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mfunc\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mcallee\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moperands\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mcallee\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msetter\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mcallee\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnewcallee\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moperands\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewcallee\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moperands\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mreplace_callee\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnewfunc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0mnewfunc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunction_type\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcallee\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunction_type\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"New function has incompatible type\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcallee\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnewfunc\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mcalled_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;34m\"\"\"Alias for llvmpy\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcallee\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0m_descr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbuf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0madd_metadata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m', '\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'{0} {1}'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                          \u001b[0;32mfor\u001b[0m \u001b[0ma\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mfnty\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcallee\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfunction_type\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;31m# Only print function type if variable-argument\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0mfnty\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvar_arg\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mty\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfnty\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;31m# Otherwise, just print the return type.\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0;31m# Fastmath flag work only in this case\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mty\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfnty\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturn_type\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mcallee_ref\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"{0} {1}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mty\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcallee\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcconv\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mcallee_ref\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"{0} {1}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcconv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcallee_ref\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"{tail}{op}{fastmath} {callee}({args}){attr}{meta}\\n\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mtail\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'tail '\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtail\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mop\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mopname\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mcallee\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcallee_ref\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mfastmath\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\" \"\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mattr\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mattr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfastmath\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0margs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mattr\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\" \"\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mattr\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mattr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mattributes\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mmeta\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stringify_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mleading_comma\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                  \u001b[0;32mif\u001b[0m \u001b[0madd_metadata\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m\"\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mdescr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_descr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbuf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0madd_metadata\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
       "\u001b[0;31mClass docstring:\u001b[0m The base class for named values.\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "call = then.instructions[2]\n",
    "call??"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<ir.Function 'fib_more' of type 'i32 (i32, i32, i32)*'>,\n",
       " <ir.Instruction '.8' of type 'i32', opname 'sub', operands (<ir.Argument '.1' of type i32>, <ir.Constant type='i32' value=1>)>,\n",
       " <ir.Argument '.3' of type i32>,\n",
       " <ir.Instruction '.9' of type 'i32', opname 'add', operands (<ir.Argument '.2' of type i32>, <ir.Argument '.3' of type i32>)>]"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "call.operands"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "store = then.instructions[-2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0;31mType:\u001b[0m            StoreInstr\n",
       "\u001b[0;31mString form:\u001b[0m     store i32 %\".10\", i32* %\".7\"\n",
       "\u001b[0;31mFile:\u001b[0m            /usr/local/miniconda3/envs/metadsl/lib/python3.7/site-packages/llvmlite/ir/instructions.py\n",
       "\u001b[0;31mSource:\u001b[0m         \n",
       "\u001b[0;32mclass\u001b[0m \u001b[0mStoreInstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mInstruction\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mval\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mptr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mStoreInstr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtypes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mVoidType\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"store\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                                         \u001b[0;34m[\u001b[0m\u001b[0mval\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mptr\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mdescr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mval\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mptr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moperands\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0malign\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0malign\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m', align %d'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0malign\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0malign\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"store {0} {1}, {2} {3}{4}{5}\\n\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mval\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mval\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mptr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mptr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0malign\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stringify_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mleading_comma\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
       "\u001b[0;31mClass docstring:\u001b[0m The base class for named values.\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "store??"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "alloca = store.operands[-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\u001b[0;31mType:\u001b[0m            AllocaInstr\n",
       "\u001b[0;31mString form:\u001b[0m     %\".7\" = alloca i32\n",
       "\u001b[0;31mFile:\u001b[0m            /usr/local/miniconda3/envs/metadsl/lib/python3.7/site-packages/llvmlite/ir/instructions.py\n",
       "\u001b[0;31mSource:\u001b[0m         \n",
       "\u001b[0;32mclass\u001b[0m \u001b[0mAllocaInstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mInstruction\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mparent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtyp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcount\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0moperands\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mcount\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcount\u001b[0m \u001b[0;32melse\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0msuper\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mAllocaInstr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparent\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtyp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mas_pointer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"alloca\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m                                          \u001b[0moperands\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0malign\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m    \u001b[0;32mdef\u001b[0m \u001b[0mdescr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbuf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"{0} {1}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mopname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpointee\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moperands\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mop\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moperands\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\", {0} {1}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mop\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mop\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_reference\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0malign\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\", align {0}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0malign\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m        \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmetadata\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
       "\u001b[0;34m\u001b[0m            \u001b[0mbuf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stringify_metadata\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mleading_comma\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
       "\u001b[0;31mClass docstring:\u001b[0m The base class for named values.\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "alloca??"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'.7'"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "alloca.name"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Is this alloca used n the endif when  it is loaded?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "%\"endif\" = endif:\n",
      "  %\".23\" = load i32, i32* %\".7\"\n",
      "  ret i32 %\".23\"\n"
     ]
    }
   ],
   "source": [
    "endif = fib_more.blocks[4]\n",
    "print(str(endif))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<ir.LoadInstr '.23' of type 'i32', opname 'load', operands [<ir.AllocaInstr '.7' of type 'i32*', opname 'alloca', operands ()>]>"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "load = endif.instructions[0]\n",
    "load"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Yes it is. So the name doesn't matter, because we refer to the block in the other function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<ir.Branch '.25' of type 'void', opname 'br', operands [<ir.Block 'main' of type 'label'>]>"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "branch = fib_more.blocks[0].instructions[-1]\n",
    "\n",
    "branch\n",
    "# main_label = branch[fib_more.blocks[0]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<ir.Block 'main' of type 'label'>"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fib_more.blocks[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lets look at a loop"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Collecting numba\n",
      "\u001b[?25l  Downloading https://files.pythonhosted.org/packages/bb/0d/db1d84ec79b223dedb72d7f1823a77797494348fea4b1809d92affea720a/numba-0.45.1-cp37-cp37m-macosx_10_9_x86_64.whl (1.9MB)\n",
      "\u001b[K    100% |████████████████████████████████| 1.9MB 4.7MB/s ta 0:00:01\n",
      "\u001b[?25hRequirement already satisfied: llvmlite>=0.29.0dev0 in /usr/local/miniconda3/envs/metadsl/lib/python3.7/site-packages (from numba) (0.29.0)\n",
      "Requirement already satisfied: numpy in /usr/local/miniconda3/envs/metadsl/lib/python3.7/site-packages (from numba) (1.16.2)\n",
      "Installing collected packages: numba\n",
      "Successfully installed numba-0.45.1\n"
     ]
    }
   ],
   "source": [
    "!pip install numba"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.environ['NUMBA_OPT'] = '3'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numba\n",
    "import numba.targets.codegen"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "mod = None\n",
    "\n",
    "original_fn = numba.targets.codegen.CodeLibrary.add_ir_module\n",
    "def add_ir_module(self, ir_module):\n",
    "    global mod\n",
    "    mod = ir_module\n",
    "    \n",
    "    return original_fn(self, ir_module)\n",
    "\n",
    "numba.targets.codegen.CodeLibrary.add_ir_module = add_ir_module"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "@numba.njit\n",
    "def loop_fn(xs):\n",
    "    v = 0\n",
    "    for i in xs:\n",
    "        v += i\n",
    "    return v"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "45"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "loop_fn(np.arange(10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Source.gv.pdf'"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "loop_fn.inspect_cfg(loop_fn.signatures[0]).display(view=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "; ModuleID = \"wrapper\"\n",
       "target triple = \"x86_64-apple-darwin17.7.0\"\n",
       "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n",
       "\n",
       "declare i32 @\"_ZN8__main__11loop_fn$244E\"(i8** %\".1\", {i8*, i32}** %\".2\") \n",
       "\n",
       "define i8* @\"_ZN7cpython8__main__11loop_fn$244E\"(i8* %\"py_closure\", i8* %\"py_args\", i8* %\"py_kws\") \n",
       "{\n",
       "entry:\n",
       "  %\".5\" = call i32 (i8*, i8*, i64, i64, ...) @\"PyArg_UnpackTuple\"(i8* %\"py_args\", i8* bitcast ([8 x i8]* @\".const.loop_fn\" to i8*), i64 0, i64 0)\n",
       "  %\".6\" = icmp eq i32 %\".5\", 0\n",
       "  %\".19\" = alloca i8*\n",
       "  store i8* null, i8** %\".19\"\n",
       "  %\"excinfo\" = alloca {i8*, i32}*\n",
       "  store {i8*, i32}* null, {i8*, i32}** %\"excinfo\"\n",
       "  br i1 %\".6\", label %\"entry.if\", label %\"entry.endif\", !prof !0\n",
       "entry.if:\n",
       "  ret i8* null\n",
       "entry.endif:\n",
       "  %\".10\" = load i8*, i8** @\"_ZN08NumbaEnv8__main__11loop_fn$244E\"\n",
       "  %\".11\" = ptrtoint i8* %\".10\" to i64\n",
       "  %\".12\" = add i64 %\".11\", 16\n",
       "  %\".13\" = inttoptr i64 %\".12\" to i8*\n",
       "  %\".14\" = bitcast i8* %\".13\" to {i8*, i8*}*\n",
       "  %\".15\" = icmp eq i8* null, %\".10\"\n",
       "  br i1 %\".15\", label %\"entry.endif.if\", label %\"entry.endif.endif\", !prof !0\n",
       "arg.end:\n",
       "  ret i8* null\n",
       "entry.endif.if:\n",
       "  call void @\"PyErr_SetString\"(i8* @\"PyExc_RuntimeError\", i8* bitcast ([20 x i8]* @\".const.missing Environment\" to i8*))\n",
       "  ret i8* null\n",
       "entry.endif.endif:\n",
       "  store i8* null, i8** %\".19\"\n",
       "  %\".23\" = call i32 @\"_ZN8__main__11loop_fn$244E\"(i8** %\".19\", {i8*, i32}** %\"excinfo\")\n",
       "  %\".24\" = load {i8*, i32}*, {i8*, i32}** %\"excinfo\"\n",
       "  %\".25\" = icmp eq i32 %\".23\", 0\n",
       "  %\".26\" = icmp eq i32 %\".23\", -2\n",
       "  %\".27\" = icmp eq i32 %\".23\", -1\n",
       "  %\".28\" = icmp eq i32 %\".23\", -3\n",
       "  %\".29\" = or i1 %\".25\", %\".26\"\n",
       "  %\".30\" = xor i1 %\".29\", -1\n",
       "  %\".31\" = icmp sge i32 %\".23\", 1\n",
       "  %\".32\" = select i1 %\".31\", {i8*, i32}* %\".24\", {i8*, i32}* undef\n",
       "  %\".33\" = load i8*, i8** %\".19\"\n",
       "  br i1 %\".29\", label %\"entry.endif.endif.if\", label %\"entry.endif.endif.endif\", !prof !1\n",
       "entry.endif.endif.if:\n",
       "  br i1 %\".26\", label %\"entry.endif.endif.if.if\", label %\"entry.endif.endif.if.endif\"\n",
       "entry.endif.endif.endif:\n",
       "  br i1 %\".31\", label %\"entry.endif.endif.endif.if\", label %\"entry.endif.endif.endif.endif\"\n",
       "entry.endif.endif.if.if:\n",
       "  call void @\"Py_IncRef\"(i8* @\"_Py_NoneStruct\")\n",
       "  ret i8* @\"_Py_NoneStruct\"\n",
       "entry.endif.endif.if.endif:\n",
       "  call void @\"Py_IncRef\"(i8* @\"_Py_NoneStruct\")\n",
       "  ret i8* @\"_Py_NoneStruct\"\n",
       ".40:\n",
       "  ret i8* null\n",
       "entry.endif.endif.endif.if:\n",
       "  call void @\"PyErr_Clear\"()\n",
       "  %\".43\" = load {i8*, i32}, {i8*, i32}* %\".32\"\n",
       "  %\".44\" = extractvalue {i8*, i32} %\".43\", 0\n",
       "  %\".45\" = load {i8*, i32}, {i8*, i32}* %\".32\"\n",
       "  %\".46\" = extractvalue {i8*, i32} %\".45\", 1\n",
       "  %\".47\" = call i8* @\"numba_unpickle\"(i8* %\".44\", i32 %\".46\")\n",
       "  %\".48\" = icmp ne i8* null, %\".47\"\n",
       "  br i1 %\".48\", label %\"entry.endif.endif.endif.if.if\", label %\"entry.endif.endif.endif.if.endif\", !prof !1\n",
       "entry.endif.endif.endif.endif:\n",
       "  br i1 %\".28\", label %\"entry.endif.endif.endif.endif.if\", label %\"entry.endif.endif.endif.endif.endif\"\n",
       "entry.endif.endif.endif.if.if:\n",
       "  call void @\"numba_do_raise\"(i8* %\".47\")\n",
       "  br label %\"entry.endif.endif.endif.if.endif\"\n",
       "entry.endif.endif.endif.if.endif:\n",
       "  br label %\".40\"\n",
       "entry.endif.endif.endif.endif.if:\n",
       "  call void @\"PyErr_SetNone\"(i8* @\"PyExc_StopIteration\")\n",
       "  br label %\".40\"\n",
       "entry.endif.endif.endif.endif.endif:\n",
       "  br i1 %\".27\", label %\"entry.endif.endif.endif.endif.endif.if\", label %\"entry.endif.endif.endif.endif.endif.endif\"\n",
       "entry.endif.endif.endif.endif.endif.if:\n",
       "  br label %\".40\"\n",
       "entry.endif.endif.endif.endif.endif.endif:\n",
       "  call void @\"PyErr_SetString\"(i8* @\"PyExc_SystemError\", i8* bitcast ([43 x i8]* @\".const.unknown error when calling native function\" to i8*))\n",
       "  br label %\".40\"\n",
       "}\n",
       "\n",
       "declare i32 @\"PyArg_UnpackTuple\"(i8* %\".1\", i8* %\".2\", i64 %\".3\", i64 %\".4\", ...) \n",
       "\n",
       "@\".const.loop_fn\" = internal constant [8 x i8] c\"loop_fn\\00\"\n",
       "@\"_ZN08NumbaEnv8__main__11loop_fn$244E\" = common global i8* null\n",
       "declare void @\"PyErr_SetString\"(i8* %\".1\", i8* %\".2\") \n",
       "\n",
       "@\"PyExc_RuntimeError\" = external global i8\n",
       "@\".const.missing Environment\" = internal constant [20 x i8] c\"missing Environment\\00\"\n",
       "@\"_Py_NoneStruct\" = external global i8\n",
       "declare void @\"Py_IncRef\"(i8* %\".1\") \n",
       "\n",
       "declare void @\"PyErr_Clear\"() \n",
       "\n",
       "declare i8* @\"numba_unpickle\"(i8* %\".1\", i32 %\".2\") \n",
       "\n",
       "declare void @\"numba_do_raise\"(i8* %\".1\") \n",
       "\n",
       "declare void @\"PyErr_SetNone\"(i8* %\".1\") \n",
       "\n",
       "@\"PyExc_StopIteration\" = external global i8\n",
       "@\"PyExc_SystemError\" = external global i8\n",
       "@\".const.unknown error when calling native function\" = internal constant [43 x i8] c\"unknown error when calling native function\\00\"\n",
       "!0 = !{ !\"branch_weights\", i32 1, i32 99 }\n",
       "!1 = !{ !\"branch_weights\", i32 99, i32 1 }"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "mod"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
